package org.dy.db.model;

import org.apache.commons.validator.GenericValidator;
import org.dy.config.XmlConvertable;
import org.jdom.Attribute;
import org.jdom.Element;

public class FieldInfo implements XmlConvertable, Comparable {
	
	protected int seq = 1;
	
	protected boolean isPk;
	protected boolean isFk;
	
	protected String name;
	protected String des;
	protected String type;
	protected int length;
	protected int mod = 3;
	// eg. required 4 or email require
	protected String restrict;
	
	protected String generatorSeq;
	protected String fkTableName;
	protected String fkModel;
	protected String fkTableField;
	// one-one one-many many-one many-many
	protected int mappingType = 1;
	
	public static String[] typeList = {"varchar", "int", "double", "date", 
		"time", "timestamp", "text", "url", "blob", "tinyint"};
	
	public static String[] restrictList = {
		"none", "int", "required", "minlength", "password", 
		"email", "float", "double", "url", "date", "time", "timestamp", "tinyint"};
	
	public boolean isRestrict(String str){
		String[] resl = this.restrict.split(" ");
		for(String res : resl){
			if(res.equals(str))
				return true;
		}
		return false;
	}
	
	public boolean valid(){
		if(this.restrict.equals("none"))
			return true;
		
		boolean r = true;
		if(this.isRestrict("required")){
			if(GenericValidator.isBlankOrNull((String)value)){
				r = false;
				return r;
			}
		}
		
		if(this.isRestrict("email")){
			if(!GenericValidator.isEmail((String)value)){
				r = false;
				return r;
			}
		}
		
		if(this.isRestrict("date")){
			if(!GenericValidator.isDate((String)value, null)){
				r = false;
				return r;
			}
		}
		
		if(this.isRestrict("int") || this.isRestrict("tinyint")){
			if(!GenericValidator.isInt((String)value)){
				r = false;
				return r;
			}
		}
		
		if(this.isRestrict("float")){
			if(!GenericValidator.isFloat((String)value)){
				r = false;
				return r;
			}
		}
		
		if(this.isRestrict("double")){
			if(!GenericValidator.isDouble((String)value)){
				r = false;
				return r;
			}
		}
		
		if(this.isRestrict("url")){
			if(!GenericValidator.isUrl((String)value)){
				r = false;
				return r;
			}
		}
	
		return r;
	}
	
	public FieldInfo getLinkField(TableLayer tl){
		FieldInfo fi = null;
		if(this.isFk && this.fkTableName != null){
			TableHeader th = tl.getByTableName(fkTableName);
			fi = th.getPkInfo();
		}
		return fi ;
	}
	
	protected Object value;
	
	public FieldInfo() {
	}
	
	public FieldInfo(String name, Object value) {
		super();
		this.name = name;
		this.value = value;
	}

	public FieldInfo(FieldInfo fi) {
		this.setFk(fi.isFk());
		this.setPk(fi.isPk());
		this.setGeneratorSeq(fi.getGeneratorSeq());
		this.setFkTableName(fi.getFkTableName());
		this.setFkModel(fi.getFkModel());
		this.setFkTableField(fi.getFkTableField());
		
		this.setMod(fi.getMod());
		this.setSeq(fi.getSeq());
		
		this.setLength(fi.getLength());
		this.setName(fi.getName());
		this.setRestrict(fi.getRestrict());
		this.setType(fi.getType());
		this.setValue(fi.getValue());
	}

	public Object getValue() {
		return value;
	}

	public void setValue(Object value) {
		this.value = value;
	}
	
	public boolean isEmpty(){
		return this.value == null;
	}
	
	private String getNullString(String str, String value){
		return str == null?value:str;
	}

	// xml interchange
	public Element getXmlElement(){
		Element ee=new Element("field");
		ee.setAttribute("name", getNullString(name, "none"));
		ee.setAttribute("des", getNullString(des, ""));
		ee.setAttribute("type", getNullString(type, "varchar"));
		ee.setAttribute("mod", mod + "");
		ee.setAttribute("seq", seq + "");
		
		ee.setAttribute("length", length + "");
		ee.setAttribute("restrict", getNullString(restrict, "none"));
		
		if(this.isPk)
			ee.setAttribute("isPk", "true");
			ee.setAttribute("generatorSeq", getNullString(generatorSeq, ""));
		if(this.isFk){
			ee.setAttribute("isFk", "true");
			ee.setAttribute("fkTableName", getNullString(fkTableName, ""));
			ee.setAttribute("fkModel", getNullString(fkModel, ""));
			ee.setAttribute("fkTableField", getNullString(fkTableField, ""));
		}
		return ee;
	}
	
	public void getFromXml(Element el) {
		// TODO Auto-generated method stub
		this.name = el.getAttributeValue("name");
		Attribute lengthStr = el.getAttribute("length");
		if(lengthStr != null)
			this.length = Integer.parseInt(lengthStr.getValue());
		
		Attribute modStr = el.getAttribute("mod");
		if(modStr != null)
			this.mod = Integer.parseInt(modStr.getValue());
		
		Attribute seqStr = el.getAttribute("seq");
		if(seqStr != null)
			this.seq = Integer.parseInt(seqStr.getValue());
		
		Attribute desStr = el.getAttribute("des");
		if(desStr != null)
			this.des = desStr.getValue();
		
		Attribute typeAttr = el.getAttribute("type");
		this.type = typeAttr == null?"varchar":typeAttr.getValue();
		
		Attribute restrictAttr = el.getAttribute("restrict");
		this.restrict = restrictAttr == null?"none":restrictAttr.getValue();
		
		if(el.getAttribute("isPk") != null)
			this.isPk = Boolean.valueOf(el.getAttributeValue("isPk"));
			if(this.isPk){
				generatorSeq = el.getAttributeValue("generatorSeq");
			}
		if(el.getAttribute("isFk") != null){
			this.isFk = Boolean.valueOf(el.getAttributeValue("isFk"));
			if(this.isFk){
				fkTableName = el.getAttributeValue("fkTableName");
				fkModel = el.getAttributeValue("fkModel");
				fkTableField = el.getAttributeValue("fkTableField");
			}
		}
	}

	public int getLength() {
		return length;
	}

	public void setLength(int length) {
		this.length = length;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getRestrict() {
		return restrict;
	}

	public void setRestrict(String restrict) {
		this.restrict = restrict;
	}

	public String getType() {
		return type;
	}

	public void setType(String type) {
		this.type = type;
	}

	public String getFkTableName() {
		return fkTableName;
	}

	public void setFkTableName(String fkTableName) {
		this.fkTableName = fkTableName;
	}

	public boolean isFk() {
		return isFk;
	}

	public void setFk(boolean isFk) {
		this.isFk = isFk;
	}

	public boolean isPk() {
		return isPk;
	}

	public void setPk(boolean isPk) {
		this.isPk = isPk;
	}

	public int compareTo(Object o) {
		FieldInfo fb = (FieldInfo) o;
		if(this.isPk)
			return -1;
		if(fb.isPk)
			return 1;
		if(this.isFk)
			return -1;
		if(fb.isFk)
			return 1;
		return this.seq - fb.seq;
	}

	public int getMappingType() {
		return mappingType;
	}

	public void setMappingType(int mappingType) {
		this.mappingType = mappingType;
	}

	public String getFkTableField() {
		return fkTableField;
	}

	public void setFkTableField(String fkTableField) {
		this.fkTableField = fkTableField;
	}

	public String getDes() {
		return des;
	}

	public void setDes(String des) {
		this.des = des;
	}

	public int getMod() {
		return mod;
	}

	public void setMod(int mod) {
		this.mod = mod;
	}

	public String getGeneratorSeq() {
		return generatorSeq;
	}

	public void setGeneratorSeq(String generatorSeq) {
		this.generatorSeq = generatorSeq;
	}

	public int getSeq() {
		return seq;
	}

	public void setSeq(int seq) {
		this.seq = seq;
	}

	public String getFkModel() {
		return fkModel;
	}

	public void setFkModel(String fkModel) {
		this.fkModel = fkModel;
	}
	
	@Override
	public String toString() {
		// TODO Auto-generated method stub
		return "{" + this.name + " = " + this.value + "}";
	}

}
